/**
 * 
 */
package com.study.singleton;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import org.springframework.core.task.support.ExecutorServiceAdapter;

/**
 * 
 * 实现单例模式有4个步骤： 1) 静态私有属性 2) 私有构造方法 3) 公有的静态的获取实例的方法 4) 公有的业务方法
 * 
 * @author Administrator
 * @date 2019年6月24日
 */
// 懒汉式（线程不安全）  -- 反射技术破解单例
public class SingletonV31 {

	private static SingletonV31 instance;
	private Person person;

	private SingletonV31() {
		if(instance != null){
//			try {  //不加这处理，可以通过反射进行单例破解
//				throw new Exception("该对象已经初始化..");
//			} catch (Exception e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
		}
		person = new Person("xiaoming");
	};

	public synchronized static SingletonV31 getInstance() {  //增加synchronized保证线程安全，但效率很低

		if (instance == null) {  //可能多个线程执行了这步
			try {
				Thread.sleep(2000);
			} catch (Exception e) {
			}
			instance = new SingletonV31();
		}
		return instance;
	}

	// 4、公有业务方法
	public String getPersonName() {
		return person.getName();
	}

	class Person {
		private String name;

		public Person(String n) {
			this.name = n;
		}

		public String getName() {
			return name;
		}
	}

	public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
		
		// 1. 使用懒汉式创建对象
		SingletonV31 instance1 = SingletonV31.getInstance();
		// 2. 使用Java反射技术初始化对象 执行无参构造函数
		Constructor<SingletonV31> declaredConstructor = SingletonV31.class.getDeclaredConstructor();
		declaredConstructor.setAccessible(true);
		SingletonV31 instance2 = declaredConstructor.newInstance();
		System.out.println(instance1 == instance2);  //通过反射破解单例
		
		System.out.println(SingletonV31.getInstance().getPersonName());
	}
}
